/*
 * onenet_data.c - OneNet数据封装库实现文件
 * 基于thingmodel-json-import.json规范实现
 * 提供各种数据类型的JSON格式封装函数
 */

#include "onenet_data.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>

// 全局变量
static uint32_t g_message_id_counter = 123456;  // 消息ID计数器
static void (*g_send_callback)(const char *json_data) = NULL;  // 发送回调函数

// 内部函数声明
static OneNet_Status_t OneNet_SendJsonData(const char *json_data);
static int OneNet_BuildPropertyJson(char *buffer, size_t buffer_size, 
                                   const char *identifier, const char *value_str, uint32_t message_id);
static int OneNet_BuildEventJson(char *buffer, size_t buffer_size, 
                                const char *event_id, const char *data_str, uint32_t message_id);

/**
 * @brief 初始化OneNet数据封装库
 */
OneNet_Status_t OneNet_Init(void)
{
    g_message_id_counter = 123456;
    g_send_callback = NULL;
    return ONENET_STATUS_SUCCESS;
}

/**
 * @brief 获取自动递增的消息ID
 */
uint32_t OneNet_GetNextMessageId(void)
{
    return g_message_id_counter++;
}

/**
 * @brief 设置OneNet发送回调函数
 */
void OneNet_SetSendCallback(void (*send_func)(const char *json_data))
{
    g_send_callback = send_func;
}

/**
 * @brief 发送布尔类型属性数据
 */
OneNet_Status_t OneNet_SendBool(bool value, uint32_t message_id)
{
    return OneNet_SendString(ONENET_PROP_BOOL, value ? "true" : "false", message_id);
}

/**
 * @brief 发送整数类型属性数据
 */
OneNet_Status_t OneNet_SendInt32(const char *identifier, int32_t value, uint32_t message_id)
{
    char value_str[32];
    snprintf(value_str, sizeof(value_str), "%d", value);
    
    char json_buffer[512];
    int len = OneNet_BuildPropertyJson(json_buffer, sizeof(json_buffer), 
                                      identifier, value_str, message_id);
    
    if (len > 0) {
        return OneNet_SendJsonData(json_buffer);
    }
    return ONENET_STATUS_ERROR;
}

/**
 * @brief 发送浮点数类型属性数据（如温度）
 */
OneNet_Status_t OneNet_SendFloat(const char *identifier, float value, uint32_t message_id)
{
    char value_str[32];
    snprintf(value_str, sizeof(value_str), "%.1f", value);
    
    char json_buffer[512];
    int len = OneNet_BuildPropertyJson(json_buffer, sizeof(json_buffer), 
                                      identifier, value_str, message_id);
    
    if (len > 0) {
        return OneNet_SendJsonData(json_buffer);
    }
    return ONENET_STATUS_ERROR;
}

/**
 * @brief 发送字符串类型属性数据
 */
OneNet_Status_t OneNet_SendString(const char *identifier, const char *value, uint32_t message_id)
{
    if (identifier == NULL || value == NULL) {
        return ONENET_STATUS_INVALID;
    }
    
    char json_buffer[1024];
    int len = OneNet_BuildPropertyJson(json_buffer, sizeof(json_buffer), 
                                      identifier, value, message_id);
    
    if (len > 0) {
        return OneNet_SendJsonData(json_buffer);
    }
    return ONENET_STATUS_ERROR;
}

/**
 * @brief 发送枚举类型属性数据
 */
OneNet_Status_t OneNet_SendEnum(const char *identifier, int value, uint32_t message_id)
{
    char value_str[32];
    snprintf(value_str, sizeof(value_str), "%d", value);
    
    char json_buffer[512];
    int len = OneNet_BuildPropertyJson(json_buffer, sizeof(json_buffer), 
                                      identifier, value_str, message_id);
    
    if (len > 0) {
        return OneNet_SendJsonData(json_buffer);
    }
    return ONENET_STATUS_ERROR;
}

/**
 * @brief 发送数组类型属性数据
 */
OneNet_Status_t OneNet_SendArray(const char *identifier, const OneNet_Array_t *array, uint32_t message_id)
{
    if (identifier == NULL || array == NULL || array->data == NULL) {
        return ONENET_STATUS_INVALID;
    }
    
    char array_str[512];
    char *ptr = array_str;
    int remaining = sizeof(array_str);
    
    ptr += snprintf(ptr, remaining, "[");
    remaining -= 1;
    
    for (int i = 0; i < array->length && remaining > 0; i++) {
        if (i > 0) {
            ptr += snprintf(ptr, remaining, ",");
            remaining -= 1;
        }
        int written = snprintf(ptr, remaining, "%d", array->data[i]);
        ptr += written;
        remaining -= written;
    }
    
    snprintf(ptr, remaining, "]");
    
    char json_buffer[1024];
    int len = OneNet_BuildPropertyJson(json_buffer, sizeof(json_buffer), 
                                      identifier, array_str, message_id);
    
    if (len > 0) {
        return OneNet_SendJsonData(json_buffer);
    }
    return ONENET_STATUS_ERROR;
}

/**
 * @brief 发送位图类型属性数据
 */
OneNet_Status_t OneNet_SendBitmap(const char *identifier, uint32_t bitmap, uint32_t message_id)
{
    char value_str[32];
    snprintf(value_str, sizeof(value_str), "%u", bitmap);
    
    char json_buffer[512];
    int len = OneNet_BuildPropertyJson(json_buffer, sizeof(json_buffer), 
                                      identifier, value_str, message_id);
    
    if (len > 0) {
        return OneNet_SendJsonData(json_buffer);
    }
    return ONENET_STATUS_ERROR;
}

/**
 * @brief 发送结构体类型属性数据
 */
OneNet_Status_t OneNet_SendStruct(const char *identifier, const OneNet_Struct_t *struct_data, uint32_t message_id)
{
    if (identifier == NULL || struct_data == NULL) {
        return ONENET_STATUS_INVALID;
    }
    
    char struct_str[256];
    snprintf(struct_str, sizeof(struct_str), 
            "{\"params1\":%d,\"params2\":%s}",
            struct_data->params1,
            struct_data->params2 ? "true" : "false");
    
    char json_buffer[1024];
    int len = OneNet_BuildPropertyJson(json_buffer, sizeof(json_buffer), 
                                      identifier, struct_str, message_id);
    
    if (len > 0) {
        return OneNet_SendJsonData(json_buffer);
    }
    return ONENET_STATUS_ERROR;
}

/**
 * @brief 发送错误事件
 */
OneNet_Status_t OneNet_SendErrorEvent(int error_code, uint32_t message_id)
{
    char error_data[128];
    snprintf(error_data, sizeof(error_data), 
            "\"ErrorCode\":%d", error_code);
    
    char json_buffer[512];
    int len = OneNet_BuildEventJson(json_buffer, sizeof(json_buffer), 
                                   ONENET_EVENT_ERROR, error_data, message_id);
    
    if (len > 0) {
        return OneNet_SendJsonData(json_buffer);
    }
    return ONENET_STATUS_ERROR;
}

/**
 * @brief 发送服务执行结果响应
 */
OneNet_Status_t OneNet_SendServiceResponse(const char *service_id, bool result, uint32_t message_id)
{
    if (service_id == NULL) {
        return ONENET_STATUS_INVALID;
    }
    
    char json_buffer[512];
    snprintf(json_buffer, sizeof(json_buffer),
            "{\r\n"
            "\"id\":\"%u\",\r\n"
            "\"version\":\"1.0\",\r\n"
            "\"code\":200,\r\n"
            "\"data\":{\r\n"
            "\"result\":%s\r\n"
            "}\r\n"
            "}\r\n",
            message_id,
            result ? "true" : "false");
    
    return OneNet_SendJsonData(json_buffer);
}

/**
 * @brief 发送多个属性的组合数据
 */
OneNet_Status_t OneNet_SendMultipleProperties(uint32_t message_id, const char *format, ...)
{
    if (format == NULL) {
        return ONENET_STATUS_INVALID;
    }
    
    va_list args;
    va_start(args, format);
    
    char params_str[1024];
    char *ptr = params_str;
    int remaining = sizeof(params_str);
    bool first = true;
    
    const char *fmt_ptr = format;
    while (*fmt_ptr && remaining > 0) {
        if (*fmt_ptr == '%' && *(fmt_ptr + 1) != '\0') {
            char type = *(fmt_ptr + 1);
            const char *identifier = va_arg(args, const char*);
            
            if (!first) {
                ptr += snprintf(ptr, remaining, ",\r\n");
                remaining -= 3;
            }
            first = false;
            
            int written = 0;
            switch (type) {
                case 'f': { // float
                    double value = va_arg(args, double);
                    written = snprintf(ptr, remaining, "\"%s\":{\"value\":%.1f}", identifier, value);
                    break;
                }
                case 'd': { // int32
                    int32_t value = va_arg(args, int32_t);
                    written = snprintf(ptr, remaining, "\"%s\":{\"value\":%d}", identifier, value);
                    break;
                }
                case 'b': { // bool
                    int value = va_arg(args, int);
                    written = snprintf(ptr, remaining, "\"%s\":{\"value\":%s}", identifier, value ? "true" : "false");
                    break;
                }
                case 's': { // string
                    const char *value = va_arg(args, const char*);
                    written = snprintf(ptr, remaining, "\"%s\":{\"value\":\"%s\"}", identifier, value);
                    break;
                }
                case 'e': { // enum
                    int value = va_arg(args, int);
                    written = snprintf(ptr, remaining, "\"%s\":{\"value\":%d}", identifier, value);
                    break;
                }
                default:
                    break;
            }
            
            ptr += written;
            remaining -= written;
            fmt_ptr += 2;
        } else {
            fmt_ptr++;
        }
    }
    
    va_end(args);
    
    char json_buffer[1536];
    snprintf(json_buffer, sizeof(json_buffer),
            "{\r\n"
            "\"id\":\"%u\",\r\n"
            "\"version\":\"1.0\",\r\n"
            "\"params\":{\r\n"
            "%s\r\n"
            "}\r\n"
            "}\r\n",
            message_id, params_str);
    
    return OneNet_SendJsonData(json_buffer);
}


/**
 * @brief 发送属性设置的响应（用于应答云端下发的指令）
 */
OneNet_Status_t OneNet_SendPropertySetResponse(const char *request_id, int code, const char *msg)
{
    if (request_id == NULL || msg == NULL) {
        return ONENET_STATUS_INVALID;
    }
    
    char json_buffer[256];
    
    // 构建标准的响应JSON
    snprintf(json_buffer, sizeof(json_buffer),
            "{\r\n"
            "\"id\":\"%s\",\r\n"
            "\"code\":%d,\r\n"
            "\"msg\":\"%s\"\r\n"
            "}\r\n",
            request_id, code, msg);
            
    return OneNet_SendJsonData(json_buffer);
}


// 内部函数实现

/**
 * @brief 发送JSON数据
 */
static OneNet_Status_t OneNet_SendJsonData(const char *json_data)
{
    if (json_data == NULL) {
        return ONENET_STATUS_INVALID;
    }
    
    if (g_send_callback != NULL) {
        g_send_callback(json_data);
        return ONENET_STATUS_SUCCESS;
    }
    
    return ONENET_STATUS_ERROR;
}

/**
 * @brief 构建属性JSON数据
 */
static int OneNet_BuildPropertyJson(char *buffer, size_t buffer_size, 
                                   const char *identifier, const char *value_str, uint32_t message_id)
{
    if (buffer == NULL || identifier == NULL || value_str == NULL) {
        return -1;
    }
    
    // 检查value_str是否是数字或布尔值（不需要引号）
    bool needs_quotes = true;
    if (strcmp(value_str, "true") == 0 || strcmp(value_str, "false") == 0) {
        needs_quotes = false;
    } else {
        // 检查是否是数字
        char *endptr;
        strtod(value_str, &endptr);
        if (*endptr == '\0') {
            needs_quotes = false;
        }
    }
    
    if (needs_quotes) {
        return snprintf(buffer, buffer_size,
                "{\r\n"
                "\"id\":\"%u\",\r\n"
                "\"version\":\"1.0\",\r\n"
                "\"params\":{\r\n"
                "\"%s\":{\"value\":\"%s\"}\r\n"
                "}\r\n"
                "}\r\n",
                message_id, identifier, value_str);
    } else {
        return snprintf(buffer, buffer_size,
                "{\r\n"
                "\"id\":\"%u\",\r\n"
                "\"version\":\"1.0\",\r\n"
                "\"params\":{\r\n"
                "\"%s\":{\"value\":%s}\r\n"
                "}\r\n"
                "}\r\n",
                message_id, identifier, value_str);
    }
}

/**
 * @brief 构建事件JSON数据
 */
static int OneNet_BuildEventJson(char *buffer, size_t buffer_size, 
                                const char *event_id, const char *data_str, uint32_t message_id)
{
    if (buffer == NULL || event_id == NULL || data_str == NULL) {
        return -1;
    }
    
    return snprintf(buffer, buffer_size,
            "{\r\n"
            "\"id\":\"%u\",\r\n"
            "\"version\":\"1.0\",\r\n"
            "\"method\":\"thing.event.%s.post\",\r\n"
            "\"params\":{\r\n"
            "%s\r\n"
            "}\r\n"
            "}\r\n",
            message_id, event_id, data_str);
} 